﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using Fluent;
using PentaBiz.Studio.Services.Plugins.Models;
using PentaBiz.Studio.Services.Plugins.PackageManager;
using PentaBiz.WpfTools;

namespace PentaBiz.Studio.Services.Plugins
{
    public partial class PluginManager : DispatcherModel
    {
        private readonly Ribbon _ribbon;


        private Dictionary<PluginPackage, PluginHostProxy> _pluginHostProxies =
            new Dictionary<PluginPackage, PluginHostProxy>();

        private PluginPackageManager _pluginPackageManager;
        private Dictionary<string, PluginPackage> pluginPackages = new Dictionary<string, PluginPackage>();


        public PluginManager(Ribbon ribbon)
        {
            _ribbon = ribbon;

            _pluginPackageManager = new PluginPackageManager();
            pluginPackages = _pluginPackageManager.GetPlugins().ToDictionary(k => k.AssemblyName, v => v);
            //search for plugins
            foreach (var pluginPackage in pluginPackages.Values)
            {
                PluginPackage package = pluginPackage;
                _pluginHostProxies.Add(pluginPackage, new PluginHostProxy(pluginPackage));
            }

            //pluginAssemblysSelector = new PluginAssemblySearch().SearchPluginAssemblies(null);
            //pluginAssemblysSelector.AsParallel().ForAll(p => p.InitializeTypeNames());


            _loadPluginControlCommand = new RelayCommand(o => LoadPluginControl(o as PluginTypeSelector));
            _closePluginCommand = new RelayCommand(o => ClosePluginControl(o as PluginControlModel));
        }

        partial void InitializePluginCommands();
        partial void InitializePluginControls();
        partial void InitializePluginServices();

        private PluginHostProxy UpdateFactory(PluginPackage pluginPackage, PluginHostProxy pluginHostProxy)
        {
            return pluginHostProxy;
        }

        private PluginHostProxy ValueFactory(PluginPackage pluginPackage)
        {
            return new PluginHostProxy(pluginPackage) {};
        }


        private static void OnPluginCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Remove:
                case NotifyCollectionChangedAction.Reset:
                    //check if oldItems is not null    
                    if (e.OldItems == null)
                        return;

                    //if any plugin view model is removed dispose it!
                    foreach (var plugin in e.OldItems.OfType<IPluginModel>())
                    {
                        plugin.Dispose();
                    }
                    break;
            }
        }

        public void Initialize()
        {
            InitializePluginCommands();
            InitializePluginControls();
            InitializePluginServices();
        }

        public void Terminate()
        {
            PluginCommandModels.ToList().ForEach(a => a.Dispose());
            PluginCommandModels.Clear();
            PluginControlModels.ToList().ForEach(a => a.Dispose());
            PluginControlModels.Clear();
            PluginServiceModels.ToList().ForEach(a => a.Dispose());
            PluginServiceModels.Clear();

            //TODO: release all Ipc based Visuals to terminate properly
            _pluginHostProxies.Clear();
        }
    }
}